<template>

  <div>

    <el-container style="height: 450px">

      <el-aside width="200px">
        <div style="width: 500px;overflow-x: scroll">
          <el-tree
              ref="tree"
              lazy
              highlight-current
              :data="fileMenu"
              :props="defaultProps"
              :load="loadNode"
              @node-click="handleNodeClick"
          >
            <!-- 文件夹图标 -->
            <template #default="{ node, data }">
              <em v-if="!data.leaf" class="el-icon-folder-opened"></em>
              <span>{{ node.label }}</span>
            </template>
          </el-tree>
        </div>

      </el-aside>
      <el-main>
        <div ref="compFileEditor" style="height: 400px;text-align:left;"></div>


      </el-main>

    </el-container>
  </div>

</template>

<script>
import {getStream, post} from '../../config/Request.js'
import {h, toRaw} from "vue";
// import JSZipUtils from "jszip-utils";
import JSZip from "jszip";
import * as monaco from "monaco-editor";
import apis from "@/request/apis.js";
import {customLanguageConfiguration, customTheme, customTokenProvider} from "@/views/comp/MonacoJavaCustom.js";
import groovyBeautify from "groovy-beautify";
// ES modules
import {SocketD} from "@noear/socket.d"
import GlobelConst from "@/config/GlobelConst.js";

export default {
  name: "ProcessCompObjectManager",
  components: {},
  // watch: {
  //   compCode() {
  //     setTimeout(function () {
  //       this.loadZip();
  //     }.bind(this), 500)
  //   }
  // },
  data() {
    return {
      zip: null,
      monacoInstance: null,
      compCode: '',
      compVersion: '',
      decorations: [],
      session:null,
      languages: null,
      fileMenu: [],
      defaultProps: {
        children: "children",
        label: "label",
        isLeaf: "leaf",
      },
    }
  },
  mounted() {

  },
  methods: {
    // 在树节点加上点击事件
    handleNodeClick(data) {
      if (data.leaf) {
        this.currentPath = data.path;
        // 将点击的文件内容显示在编译框内
        this.zip
            .file(data.path)
            .async("string")
            .then((res) => {
              // toRaw(this.monacoInstance).setValue(res);
              var s = data.label;
              /*只获取后缀*/
              var suffix = s.match(/[^.]+$/)[0];//txt
              if (!suffix) {
                suffix = "txt";
              }
              //重新转换一下
              if (suffix == 'js') {
                suffix = "javascript";
              }
              if (suffix == 'properties') {
                suffix = "ini";
              }
              // 新建一个model
              const newModel = monaco.editor.createModel(res, suffix);
              // 设置编辑器的model为newModel
              toRaw(this.monacoInstance).setModel(newModel);

              //target目录需要设置为只读
              if (data.path.startsWith("target")) {
                toRaw(this.monacoInstance).updateOptions({readOnly: true})
              }
              // else {
              //   toRaw(this.monacoInstance).updateOptions({readOnly: false})
              // }
            });
      }
    },
    // 保存编辑
    saveValue() {
      if (this.currentPath) {
        const newValue = toRaw(this.monacoInstance).getValue();
        this.zip.file(this.currentPath, newValue);
      }
    },
    async startConnect() {
      var baseUrl = GlobelConst.baseUrl;
      const sq = await apis.post("/square-lake/debugger/connect", {});
      console.log(sq);
      if(this.session){
        this.session.close();
      }

      const c = baseUrl.split(":");
      const url = c[0]+":"+sq;
      this.session = await SocketD.createClient(`sd:ws://${url}/?u=a&p=2`)
           .open();
      console.log(this.session);

    },
    async disconnect() {
      //var baseUrl = GlobelConst.baseUrl;
      const sq = await apis.post("/square-lake/debugger/disconnect", {});
      if(this.session){
        this.session.close();
      }
      // const session = await SocketD.createClient(`sd:ws://${baseUrl}/?token=1b0VsGusEkddgr3d`)
      //     .open()
    },
    // 打包
    pack() {
      this.zip.generateAsync({type: "blob"})
          .then(function (content) {

            this.blobToBase64(content).then(base64Data => {
              this.saveFile(base64Data);
            })
            // 保存或上传操作
            // saveAs(content, "hello.zip");
          }.bind(this));
    },
    saveFile(file) {
      // alert("现在不允许保存，因为自动构建没做好");
      apis.post("/square-lake/process/comp/object/save_and_rebuild", {
        compVersion: this.compVersion, compCode: this.compCode,
        compFile: file
      });
      this.$notify({
        title: '提示',
        message: h('i', {style: 'color: teal'}, '上传成功，正在自动构建，请关注构建状态')
      });
      toRaw(this.monacoInstance).setValue("");
    },
    blobToBase64(blob) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onloadend = () => {
          resolve(reader.result);
        };
        reader.onerror = reject;
        reader.readAsDataURL(blob);
      });
    },
    getMenuList(zip) {
      const menu = [];
      // 循环当前文件夹目录
      console.log(zip)
      zip.forEach((relativePath, file) => {
        const dir = relativePath.split("/");
        var d = dir[0];
        if (d == "target") {
          return
        }


        // // 文件夹
        // if (dir.length === 2 && file.dir) {
        //   menu.push({
        //     label: dir[0],
        //     leaf: false,
        //     path: file.name,
        //   });
        // }

        const path = zip.root ? zip.root + dir[0] : dir[0];
        if (dir.length > 1) {

          let findFlag = false;
          for (const m of menu) {
            if (m.path == path) {
              findFlag = true;
            }
          }
          if (findFlag) {
            return;
          }
          menu.push({
            label: dir[0],
            leaf: false,
            path: path
          });

          return;
        }

        // 文件
        if (!dir.dir) {
          for (let c of dir) {
            menu.push({
              label: c,
              leaf: true,
              path: file.name,
            });
          }

        }

      });
      return menu;
    },
    // 加载子目录
    loadNode(node, resolve) {
      if (node.level === 0) return;
      // 把点击的文件夹路径传入
      const child = this.getMenuList(this.zip.folder(node.data.path));
      resolve(child);
    },
    getBreakpoint() {
      let breakpointLines = [];
      if (toRaw(this.monacoInstance)) {
        let decorations = toRaw(this.monacoInstance).getModel().getAllDecorations();
        let ids = [];
        for (let decoration of decorations) {
          if (
              decoration.options.linesDecorationsClassName === "breakpoints-code"
          ) {
            breakpointLines.push(decoration.range.startLineNumber);
          }
        }
      }
    },
    removeFakeBreakPoint() {
      let model = toRaw(this.monacoInstance).getModel();
      this.decorations = model.deltaDecorations(this.decorations, []);
    },
    hasBreakPoint(line) {
      let decorations = toRaw(this.monacoInstance).getLineDecorations(line);
      for (let decoration of decorations) {
        if (
            decoration.options.linesDecorationsClassName === "breakpoints-code"
        ) {
          return true;
        }
      }
      return false;
    },
    async addBreakPoint(line) {
      let model = toRaw(this.monacoInstance).getModel();
      if (!model) return;
      let value = [
        {
          range: new monaco.Range(line, 1, line, 1),
          options: {
            isWholeLine: true,
            linesDecorationsClassName: "breakpoints-code"
          }
        },
        {
          range: new monaco.Range(line, null, line, null),
          options: {
            isWholeLine: true,
            className: "debug-line-color"
          }
        }
      ];
      model.deltaDecorations([], value);
    },
    async removeBreakPoint(line) {
      let model = toRaw(this.monacoInstance).getModel();
      if (!model) return;
      let decorations;
      let ids = [];
      if (line !== undefined) {
        decorations = toRaw(this.monacoInstance).getLineDecorations(line);
      } else {
        decorations = toRaw(this.monacoInstance).getModel().getAllDecorations();
      }
      for (let decoration of decorations) {
        if (decoration.options.className === "debug-line-color") {
          ids.push(decoration.id);
        }
        if (
            decoration.options.linesDecorationsClassName === "breakpoints-code"
        ) {
          ids.push(decoration.id);
        }
      }
      if (ids && ids.length) {
        model.deltaDecorations(ids, []);
      }
    },
    addFakeBreakPoint(line) {
      let model = toRaw(this.monacoInstance).getModel();
      if (this.hasBreakPoint(line)) return;
      let value = {
        range: new monaco.Range(line, 1, line, 1),
        options: {
          isWholeLine: true,
          linesDecorationsClassName: "breakpoints-fake-code"
        }
      };
      this.decorations = model.deltaDecorations(this.decorations, [value]);
    },
    async loadZip(compCode, compVersion, readonly, connected) {
      this.compCode = compCode;
      this.compVersion = compVersion;
      if (connected) {
        this.startConnect();
      }
      if (!this.monacoInstance) {
        monaco.languages.register({id: "customjava"});
        monaco.languages.setMonarchTokensProvider("customjava", customTokenProvider);
        monaco.editor.defineTheme("customTheme", customTheme);
        monaco.languages.setLanguageConfiguration(
            "customjava",
            customLanguageConfiguration(monaco)
        );
        //customjava代码格式化问题，这里使用了groovyBeautify 他是npm里第三方格式化java代码的插件库
        monaco.languages.registerDocumentFormattingEditProvider("customjava", {
          provideDocumentFormattingEdits: function (model, options, token) {
            var formattedCode = groovyBeautify(model.getValue());
            return [
              {
                range: model.getFullModelRange(),
                text: formattedCode
              }
            ];
          }
        });

        //customjava代码提示问题
        //这里使用了registerCompletionItemProvider
        this.languages = monaco.languages.registerCompletionItemProvider(
            "customjava",
            {
              provideCompletionItems: () => {
                let suggestions = [];
                suggestions.push({
                  label: "提示信息",
                  //插入文本的方式，具体可以console monaco.languages.CompletionItemKind
                  kind: monaco.languages.CompletionItemKind,
                  insertText: "插入的文本",
                  documentation: "插入的详情"
                });
                return {
                  suggestions: suggestions
                };
              }
            }
        )

        this.monacoInstance = monaco.editor.create(this.$refs.compFileEditor, {
              value: `//请选择文件进行编辑`,
              language: "customjava",
              contextmenu: true,
              fontSize: 16,
              theme: "customTheme", // 主题
              folding: true, // 是否折叠
              inherit: true,
              minimap: {
                enabled: true
              },
              foldingHighlight: true, // 折叠等高线
              foldingStrategy: "indentation", // 折叠方式  auto | indentation
              showFoldingControls: "always", // 是否一直显示折叠 always | mouseover
              disableLayerHinting: true, // 等宽优化
              emptySelectionClipboard: false, // 空选择剪切板
              selectionClipboard: false, // 选择剪切板
              automaticLayout: true, // 自动布局
              codeLens: false, // 代码镜头
              scrollBeyondLastLine: false, // 滚动完最后一行后再滚动一屏幕
              colorDecorators: true, // 颜色装饰器
              accessibilitySupport: "off", // 辅助功能支持  "auto" | "off" | "on"
              lineNumbers: "on", // 行号 取值： "on" | "off" | "relative" | "interval" | function
              lineNumbersMinChars: 5, // 行号最小字符   number
              enableSplitViewResizing: false,
              readOnly: readonly || false, //是否只读  取值 true | false
            }
        );
        // 编辑监听
        toRaw(this.monacoInstance).onDidChangeModelContent(() => {
          this.saveValue();
        });


        toRaw(this.monacoInstance).onMouseMove(e => {
          this.removeFakeBreakPoint();
          if (
              e.target.detail &&
              e.target.detail.offsetX &&
              e.target.detail.offsetX >= 0 &&
              e.target.detail.offsetX <= 40
          ) {
            let line = e.target.position.lineNumber;
            let lineContent = toRaw(this.monacoInstance)
                .getModel()
                .getLineContent(line)
                .trim();
            if (lineContent) {
              this.addFakeBreakPoint(line);
            }
          }
        });
        toRaw(this.monacoInstance).onMouseDown(e => {
          if (
              e.target.detail &&
              e.target.detail.offsetX &&
              e.target.detail.offsetX >= 0 &&
              e.target.detail.offsetX <= 40
          ) {
            // alert(2)
            let line = e.target.position.lineNumber;
            let lineContent = toRaw(this.monacoInstance)
                .getModel()
                .getLineContent(line)
                .trim();
            if (lineContent) {
              if (!this.hasBreakPoint(line)) {
                this.addBreakPoint(line);
              } else {
                this.removeBreakPoint(line);
              }
              this.getBreakpoint();
            }
          }
        });

      } else {
        toRaw(this.monacoInstance).setValue("//请选择文件进行编辑");
      }

      this.zip = null;
      this.fileMenu = [];

      var data = await getStream("/square-lake/process/comp/object/get_file?compCode=" + this.compCode + "&compVersion=" + this.compVersion);
      this.zip = new JSZip();
      //解压
      this.zip.loadAsync(data).then((zip) => {
        // this.folderZhankai(zip);
        this.fileMenu = this.getMenuList(zip);
      });
    }
  }
}
</script>

<style scoped>


</style>